package com.mlan.userap.untils;

import android.content.Context;
import android.media.AudioManager;

import org.json.JSONObject;


import org.webrtc.DataChannel;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.PeerConnection;
import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;


import java.util.Collections;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

public class WebRTCClient {
    private PeerConnectionFactory factory;
    private PeerConnection peerConnection;
    private AudioTrack audioTrack;
    private WebSocket ws;
    private String clientId;
    private String targetId; // 目标用户ID，由应用逻辑指定
    private Context context;

    public WebRTCClient(Context context, String targetId) {
        this.context = context;
        this.targetId = targetId;
        initializeWebRTC();
        connectToSignalingServer();
    }

    private void initializeWebRTC() {
        PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(context).createInitializationOptions());
        factory = PeerConnectionFactory.builder().createPeerConnectionFactory();

        // 创建音频源
        AudioSource audioSource = factory.createAudioSource(new MediaConstraints());
        audioTrack = factory.createAudioTrack("audio_track", audioSource);

        // 配置 ICE 服务器（这里使用 Google 的 STUN 服务器）
        PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer();
        PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(Collections.singletonList(iceServer));

        peerConnection = factory.createPeerConnection(config, new PeerConnection.Observer() {
            @Override
            public void onIceCandidate(IceCandidate candidate) {
                sendSignalingMessage("ice", candidate.sdp, targetId);
            }

            @Override
            public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {

            }

            @Override
            public void onAddStream(MediaStream stream) {}
            @Override
            public void onRemoveStream(MediaStream stream) {}
            @Override
            public void onDataChannel(DataChannel dataChannel) {}
            @Override
            public void onRenegotiationNeeded() {}
            @Override
            public void onIceConnectionChange(PeerConnection.IceConnectionState newState) {}

            @Override
            public void onIceConnectionReceivingChange(boolean b) {

            }

            @Override
            public void onIceGatheringChange(PeerConnection.IceGatheringState newState) {}
            @Override
            public void onSignalingChange(PeerConnection.SignalingState newState) {}
        });

        peerConnection.addTrack(audioTrack);
    }

    private void connectToSignalingServer() {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url("ws://localhost:5000/ws").build();
        ws = client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                clientId = java.util.UUID.randomUUID().toString();
                startCall();
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {
                try {
                    JSONObject json = new JSONObject(text);
                    String type = json.getString("type");
                    String data = json.getString("data");

                    if ("offer".equals(type)) {
                        peerConnection.setRemoteDescription(new SimpleSdpObserver(), new SessionDescription(SessionDescription.Type.OFFER, data));
                        createAnswer();
                    } else if ("answer".equals(type)) {
                        peerConnection.setRemoteDescription(new SimpleSdpObserver(), new SessionDescription(SessionDescription.Type.ANSWER, data));
                    } else if ("ice".equals(type)) {
                        peerConnection.addIceCandidate(new IceCandidate("", 0, data));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void startCall() {
        peerConnection.createOffer(new SimpleSdpObserver() {
            @Override
            public void onCreateSuccess(SessionDescription sdp) {
                peerConnection.setLocalDescription(new SimpleSdpObserver(), sdp);
                sendSignalingMessage("offer", sdp.description, targetId);
            }
        }, new MediaConstraints());
    }

    private void createAnswer() {
        peerConnection.createAnswer(new SimpleSdpObserver() {
            @Override
            public void onCreateSuccess(SessionDescription sdp) {
                peerConnection.setLocalDescription(new SimpleSdpObserver(), sdp);
                sendSignalingMessage("answer", sdp.description, targetId);
            }
        }, new MediaConstraints());
    }

    private void sendSignalingMessage(String type, String data, String targetId) {
        try {
            JSONObject json = new JSONObject();
            json.put("type", type);
            json.put("clientId", clientId);
            json.put("targetId", targetId);
            json.put("data", data);
            ws.send(json.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // SDP 观察者简化类
    private static class SimpleSdpObserver implements SdpObserver {
        @Override
        public void onCreateSuccess(SessionDescription sdp) {}
        @Override
        public void onSetSuccess() {}
        @Override
        public void onCreateFailure(String error) {}
        @Override
        public void onSetFailure(String error) {}
    }

    public void setAudioOutput() {
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        audioManager.setSpeakerphoneOn(true);
    }
}